﻿using System;
using System.Collections.ObjectModel;
using System.Configuration;
using System.Diagnostics;
using System.Reflection;
using System.Collections.Generic;
using System.IdentityModel.Policy;

namespace SecurityTokenServiceNS
{
    public class AddInTool
    {
		private static List<IRSTProcessor> _rstProcessorModules = new List<IRSTProcessor>();
		private static IProofProcessor _proofProcessorModule;
		private static List<IIssuedClaimsProcessor> _issuedClaimsProcessorModules = new List<IIssuedClaimsProcessor>();
		private static List<IIssuedTokenProcessor> _issuedTokenProcessorModules = new List<IIssuedTokenProcessor>();
		private static List<IRSTRProcessor> _rstrProcessorModules = new List<IRSTRProcessor>();

		#region properties
		public static List<IRSTProcessor> RstProcessorModules
		{
			get { return _rstProcessorModules; }
		}
		public static IProofProcessor ProofProcessorModule
		{
			get { return _proofProcessorModule; }
		}
		public static List<IIssuedClaimsProcessor> IssuedClaimsProcessorModules
		{
			get { return _issuedClaimsProcessorModules; }
		}
		public static List<IIssuedTokenProcessor> IssuedTokenProcessorModules
		{
			get { return _issuedTokenProcessorModules; }
		}
		public static List<IRSTRProcessor> RstrProcessorModules
		{
			get { return _rstrProcessorModules; }
		}
		#endregion

		public static void LoadAddIns()
		{
			string path = StsConfiguration.Current.ExtensionModules.Path;

			foreach (ExtensionModuleConfiguration aic in StsConfiguration.Current.ExtensionModules.RstProcessor)
				_rstProcessorModules.Add(GetAddIn<IRSTProcessor>(aic.Type, path + aic.Lib));

			ExtensionModuleConfiguration addin = StsConfiguration.Current.ExtensionModules.ProofProcessor.GetFirst();
			_proofProcessorModule = GetAddIn<IProofProcessor>(addin.Type, path + addin.Lib);

			foreach (ExtensionModuleConfiguration aic in StsConfiguration.Current.ExtensionModules.IssuedClaimsProcessor)
				_issuedClaimsProcessorModules.Add(GetAddIn<IIssuedClaimsProcessor>(aic.Type, path + aic.Lib));

			foreach (ExtensionModuleConfiguration aic in StsConfiguration.Current.ExtensionModules.IssuedTokenProcessor)
				_issuedTokenProcessorModules.Add(GetAddIn<IIssuedTokenProcessor>(aic.Type, path + aic.Lib));

			foreach (ExtensionModuleConfiguration aic in StsConfiguration.Current.ExtensionModules.RstrProcessor)
				_rstrProcessorModules.Add(GetAddIn<IRSTRProcessor>(aic.Type, path + aic.Lib));
		}

		public static List<IAuthorizationPolicy> GetAuthorizationPolicies()
		{
			string path = StsConfiguration.Current.ExtensionModules.Path;
			List<IAuthorizationPolicy> aPolicies = new List<IAuthorizationPolicy>();

			foreach (ExtensionModuleConfiguration aic in StsConfiguration.Current.ClaimPolicies)
				aPolicies.Add(GetAddIn<IAuthorizationPolicy>(aic.Type, path + aic.Lib));
			return aPolicies;
		}

		static private T GetAddIn<T>(string type, string path)
		{
			Debug.Assert(typeof(T).IsInterface);
			try
			{
				Assembly assembly = Assembly.LoadFile(path);
				foreach (Type t in assembly.GetTypes())
				{
					if (!t.IsClass || t.Name != type)
						continue;
					return (T)Activator.CreateInstance(t);
				}
			}
			catch (Exception ex)
			{
				Console.WriteLine(String.Format("Error loading Extension Module {0} from {1}: {2}", type, path, ex.Message));
			}
			return default(T);
		} 
    }
}
